package com.google.webmusic.ws;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import org.apache.log4j.Logger;

import com.google.webmusic.model.Member;
import com.google.webmusic.util.ExceptionBuilder;
import com.google.webmusic.util.RequestUtil;

@ServerEndpoint(value = "/ws.do")
public class WebmusicWebSocketEndpoint {
    private static final Logger LOGGER = Logger.getLogger(WebmusicWebSocketEndpoint.class);
    
    private Socket socket;
    
	public WebmusicWebSocketEndpoint() {
		super();
		LOGGER.debug("test, created one ServerEndpoint instance");
	}

	@OnOpen
    public void onOpen(Session session) {
		session.setMaxBinaryMessageBufferSize(100000);
		session.setMaxTextMessageBufferSize(100000);
		session.setMaxIdleTimeout(5*60*1000);
		RequestUtil.debugSession(session, LOGGER);
    	Map<String, List<String>> params=session.getRequestParameterMap();
    	
    	String roomId=RequestUtil.getParameter(params, "rm");
    	String userId=RequestUtil.getParameter(params, "uid");
    	
    	LOGGER.debug(roomId+","+userId);
    	if(roomId==null||userId==null){
    		try {
    			session.getBasicRemote().sendText(new Model<Void>(false, "arguments missing.").toString());
				session.close();
			} catch (IOException e) {
				LOGGER.error(ExceptionBuilder.buildStack(e));
			}
			return ;
		}
    	
    	Member member=new Member(roomId, userId);
    	Socket s=WSUserManager.getMemberSocket(member);
    	if(s!=null){
    		try {
				s.session.close();//close previous socket
			} catch (IOException e) {
				LOGGER.error(ExceptionBuilder.buildStack(e));
			}
    	}
    	socket= new Socket(session, member);
    	WSUserManager.addMember(socket, member);
    	
    }

    @OnClose
    public void onClose() {
    	try {
    		Member member=socket.member;
    		Set<Member> roomMembers=WSUserManager.getRoomMembers(member);
    		for(Member m:roomMembers){
    			if(m.equals(member)){
    				continue;
    			}
    			Socket mSocket=WSUserManager.getMemberSocket(m);
    			mSocket.session.getBasicRemote().sendText(new Model<Void>(false, "offline").toString());
    		}
    		WSUserManager.offlineMember(member);
    		
			LOGGER.debug(socket+" is closed");
		} catch (IOException e) {
			LOGGER.error(ExceptionBuilder.buildStack(e));
		}
    }
    /**
     * message repeater
     * @param message
     */
    @OnMessage
    public void onRepeatMessage(String json) {
    	//just repeat to others in room
    	Member member=socket.member;
		Set<Member> roomMembers=WSUserManager.getRoomMembers(member);
		for(Member m:roomMembers){
			if(m.equals(member)){
				continue;
			}
			Socket mSocket=WSUserManager.getMemberSocket(m);
			try {
				mSocket.session.getBasicRemote().sendText(json);
			} catch (IOException e) {
				LOGGER.error(ExceptionBuilder.buildStack(e));
			}
		}
    }

    @OnError
    public void onError(Throwable t) throws Throwable {
    	LOGGER.error("Chat Error: " + t.toString(), t);
    }
   
}
